package com.myk.game.gobangchess.rooms;

import com.myk.game.gobangchess.CustomBottom;
import com.myk.game.gobangchess.DataManager;
import com.myk.game.gobangchess.Room;
import com.myk.game.gobangchess.constants.ColorCost;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.signs.GroundSign;
import com.myk.game.gobangchess.utils.GridsUtils;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;

/**
 * 湃凼
 */
public class PahTumRoom extends Room {

    private final static int[][] dxdys = new int[][]{{1, 0}, {1, 1}, {0, 1}, {-1, 1}};
    CustomBottom oldRule = new CustomBottom(this, "禁5", p -> {
        prepareBoard();
        player_black.clearCustomBottom();
        player_black.dispatchCustomBottom();
        player_white.clearCustomBottom();
        player_white.dispatchCustomBottom();
        noticeBlackMove();
    });
    CustomBottom newRule = new CustomBottom(this, "禁7", p -> {
        prepareBoardNew();
        player_black.clearCustomBottom();
        player_black.dispatchCustomBottom();
        player_white.clearCustomBottom();
        player_white.dispatchCustomBottom();
        noticeBlackMove();
    });

    public PahTumRoom(String roomName) {
        super(roomName, "多连长直线", "湃凼", GridsUtils.createEmptyGrids(7, 7), true, true);
    }

    @Override
    public String getRuleText() {
        return "湃凼/冰滩（Pah'Tum）\n"
            + "7路棋盘，开局随机形成5格冰凼，玩家不可于冰凼内落子\n"
            + "轮流落1子，棋盘满后结算分数：\n"
            + "每个N连算N分，总分更高一方胜";
    }

    @Override
    protected void onStartPrepare() {
        player_black.registerCustomBottom(oldRule, newRule);
        player_white.registerCustomBottom(oldRule, newRule);
        noticeNoMove();
    }

    private void prepareBoard() {
        List<Point> points = new ArrayList<>();
        points.add(new Point(3, 3));
        for (int i = 0; i < 4; i++) {
            Point point = GridsUtils.gridsBuildWall(new Point(0, 0), new Point(6, 6), points.toArray(new Point[0]));
            points.add(point);
        }
        for (Point point : points) {
            curGrids[point.x][point.y] = 9;
        }
    }

    private void prepareBoardNew() {
        List<Point> points = new ArrayList<>();
        for (int i = 0; i < 7; i++) {
            Point point = GridsUtils.gridsBuildWall(new Point(0, 0), new Point(6, 6), points.toArray(new Point[0]));
            points.add(point);
        }
        for (Point point : points) {
            curGrids[point.x][point.y] = 9;
        }
    }

    @Override
    public String getGameInfo() {
        calScore();
        return super.getGameInfo();
    }

    @Override
    public void doRule(int row, int col, int value) {
        if (curGrids[row][col] != 0) {
            return;
        }
        curGrids[row][col] = value;
        signList.clear();
        signList.add(new GroundSign(getIndex(row, col), "#00000000", ColorCost.NEW_PUT_POINT, 1f, 0, 0));
        stepAdd();
        if (GridsUtils.getDataCount(curGrids, 0) == 0) {
            calScore();
            onGameOver();
            return;
        }
        if (cur == 1) {
            noticeWhiteMove();
        } else {
            noticeBlackMove();
        }
    }

    //当游戏结束时，各种操作
    private void onGameOver() {
        if (blackScore > whiteScore) {
            String blackWinMsg = player_black.getNickNameOrTemp() + "执黑棋战胜" + player_white.getNickNameOrTemp();
            doOver(WinMode.BLACK_WIN, blackWinMsg);
        } else if (whiteScore > blackScore) {
            String whiteWinMsg = player_white.getNickNameOrTemp() + "执白棋战胜" + player_black.getNickNameOrTemp();
            doOver(WinMode.WHITE_WIN, whiteWinMsg);
        } else {
            String bothWinMsg = player_black.getNickNameOrTemp() + "-黑棋战平" + player_white.getNickNameOrTemp() + "-白棋";
            doOver(WinMode.BOTH_DRAW, bothWinMsg);
        }
    }

    private void calScore() {
        blackScore = 0;
        whiteScore = 3;
        for (int x = 0; x < curGrids.length; x++) {
            for (int y = 0; y < curGrids[0].length; y++) {
                for (int[] dxdy : dxdys) {
                    calOneScore(x, y, dxdy[0], dxdy[1]);
                }
            }
        }
    }

    private void calOneScore(int x, int y, int dx, int dy) {
        final int value = curGrids[x][y];
        if (value != 1 && value != 2) {
            return;
        }
        int length = 0;
        int score = 0;
        while (isInGrids(x, y) && curGrids[x][y] == value) {
            length += 1;
            if (length >= 3) {
                score += length;
            }
            x += dx;
            y += dy;
        }
        if (value == 1) {
            blackScore += score;
        } else {
            whiteScore += score;
        }
    }

    private boolean isInGrids(int row, int col) {
        return row >= 0 && row < curGrids.length && col >= 0 && col < curGrids[0].length;
    }
}
